import initTimer from './timer'

class Controller {
    constructor(player) {
        this.timer = initTimer()
        this.player = player
        Controller.prototype.__h = player.property.highlight
        this.volume = player.property.volume || .1

        this.__initDOM()
        this.__initEvent()
    }

    __initDOM() {
        this.player.template.bottom.innerHTML = `
            <div class="z-player_controller-bar">
                <div class="z-player_controller-bar_time" style="display: none">00:00</div>
                <div class="z-player_controller-bar_loaded" style="width: 0;"></div>
                <div class="z-player_controller-bar_played" style="width: 0;">
                    <span class="z-player_controller-bar_thumb"></span>
                </div>
                <div class="z-player_controller-bar_highlight"></div>
            </div>
            <div class="z-player_controller-box">
                <div class="z-player_controller-box_left">
                    <span class="z-player_controller-box-icon z-player_controller-play-button">${this.player.__icons.play}</span>
                    <span class="z-player_controller-box-time">
                        <span class="z-player_controller-box-time__current">00:00</span> /
                        <span class="z-player_controller-box-time__duration">00:00</span>
                    </span>
                </div>
                <div class="z-player_controller-box_right">
                    <span class="z-player_controller-box-icon z-player_controller-setting-button">${this.player.__icons.setting}</span>
                    ${this.player.__util.isMobile ? '' : `
                    <span class="z-player_controller-box-icon z-player_controller-volume-button">${this.player.__icons.volume}</span>
                    `}
                    ${this.player.__util.isFirefox || this.player.__util.isMobile ? '' : `
                    <span class="z-player_controller-box-icon z-player_controller-pip-button" >${this.player.__icons.pip}</span>
                    `}
                    <span class="z-player_controller-box-icon z-player_controller-full-web-button">${this.player.__icons.fullWeb}</span>
                    <span class="z-player_controller-box-icon z-player_controller-full-button">${this.player.__icons.full}</span>
                    <div class="z-player_controller-rate-wrap" style="display: none">
                        <div class="z-player_controller-rate-value">2</div>
                        <div class="z-player_controller-rate-value">1.5</div>
                        <div class="z-player_controller-rate-value">1</div>
                        <div class="z-player_controller-rate-value">0.75</div>
                        <div class="z-player_controller-rate-value">0.5</div>
                    </div>
                    ${this.player.__util.isMobile ? '' : `
                    <div class="z-player_controller-volume-wrap" style="display: none">
                        <span class="z-player_controller-volume-value">${~~(this.player.property.volume * 100)}</span>
                        <div class="z-player_controller-volume-bar">
                            <div class="z-player_controller-volume-bar_current" style="height: ${~~(this.player.property.volume * 100)}%;">
                                <span class="z-player_controller-volume-bar_thumb"></span>
                            </div>
                        </div>
                    </div>
                    `}
                </div>
            </div>
        `
        this.bar = this.player.template.bottom.querySelector('.z-player_controller-bar')
        this.barTime = this.player.template.bottom.querySelector('.z-player_controller-bar_time')
        this.barLoaded = this.player.template.bottom.querySelector('.z-player_controller-bar_loaded')
        this.barPlayed = this.player.template.bottom.querySelector('.z-player_controller-bar_played')
        this.barHighlight = this.player.template.bottom.querySelector('.z-player_controller-bar_highlight')
        // this.box = this.player.template.bottom.querySelector('.z-player_controller-box')
        this.playButton = this.player.template.bottom.querySelector('.z-player_controller-play-button')
        this.current = this.player.template.bottom.querySelector('.z-player_controller-box-time__current')
        this.duration = this.player.template.bottom.querySelector('.z-player_controller-box-time__duration')
        this.volumeButton = this.player.template.bottom.querySelector('.z-player_controller-volume-button')
        this.settingButton = this.player.template.bottom.querySelector('.z-player_controller-setting-button')
        this.pipButton = this.player.template.bottom.querySelector('.z-player_controller-pip-button')
        this.fullWebButton = this.player.template.bottom.querySelector('.z-player_controller-full-web-button')
        this.fullButton = this.player.template.bottom.querySelector('.z-player_controller-full-button')
        this.volumeWrap = this.player.template.bottom.querySelector('.z-player_controller-volume-wrap')
        this.volumeValue = this.player.template.bottom.querySelector('.z-player_controller-volume-value')
        this.volumeBar = this.player.template.bottom.querySelector('.z-player_controller-volume-bar')
        this.volumeBarCurrent = this.player.template.bottom.querySelector('.z-player_controller-volume-bar_current')
        this.rateWrap = this.player.template.bottom.querySelector('.z-player_controller-rate-wrap')
        this.rateItems = this.rateWrap.getElementsByClassName('z-player_controller-rate-value')
    }

    highlight(h) {
        if (h) this.__h = h
        if (!this.__h.data || !(this.__h.data instanceof Array)) this.__h.data = []
        if (!this.player.video.duration || this.player.video.duration === Infinity) return
        this.barHighlight.innerHTML = ''
        for (let i = 0; i < this.__h.data.length; i++) {
            let node = document.createElement('span')
            node.className = 'z-player_controller-bar_highlight-item'
            node.title = this.__h.data[i].text
            let s = this.__h.data[i].time / this.player.video.duration
            node.style['left'] = 'calc(' + (s * 100) + '% - 3px)'
            this.barHighlight.appendChild(node)
        }
    }

    __initEvent() {
        this.player.__event.on('durationchange', () => {
            if (!this.player.video.duration || this.player.video.duration === Infinity) return
            this.duration.innerText = this.player.__util.secondToTime(this.player.video.duration)
            this.highlight()
        })
        this.player.__event.on('play', () => {
            this.playButton.innerHTML = this.player.__icons.pause
        })
        this.player.__event.on('pause', () => {
            this.playButton.innerHTML = this.player.__icons.play
        })
        this.player.__event.on('timeupdate', () => {
            this.barPlayed.style['width'] = this.player.video.currentTime / this.player.video.duration * 100 + '%'
            this.current.innerText = this.player.__util.secondToTime(this.player.video.currentTime)
        })
        this.player.__event.on('progress', () => {
            let percentage = 0
            if (this.player.video.buffered.length && this.player.video.duration) {
                for (let i = 0; i < this.player.video.buffered.length; i++) {
                    // 寻找当前时间之后最近的点
                    if (this.player.video.buffered.start(this.player.video.buffered.length - 1 - i) < this.player.video.currentTime) {
                        percentage = this.player.video.buffered.end(this.player.video.buffered.length - 1 - i) / this.player.video.duration
                        break
                    }
                }
            }
            this.barLoaded.style['width'] = percentage * 100 + '%'
        })
        this.player.__event.on('volumechange', () => {
            let muted = this.player.video.volume === 0
            this.player.video.muted = muted
            if (this.volumeButton) {
                this.volumeButton.innerHTML = muted ? this.player.__icons.volumeOff : this.player.__icons.volume
                this.volumeValue.innerText = ~~(this.player.video.volume * 100)
                this.volumeBarCurrent.style['height'] = this.player.video.volume * 100 + '%'
            }
        })
        this.player.__event.on('destroy', () => {
            this?.__volumeRemove()
        })

        const barHover = e => {
            let s = (e.clientX || e.changedTouches[0].clientX) - this.player.__util.getBoundingClientRectViewLeft(this.bar)
            let percentage = s < 0 ? 0 : s / this.bar.clientWidth
            if (this.player.container.clientWidth - s < this.barTime.clientWidth) {
                this.barTime.style.removeProperty('left')
                this.barTime.style['right'] = '0'
            } else if (s - 25 > 0) {
                this.barTime.style.removeProperty('right')
                this.barTime.style['left'] = s - 25 + 'px'
            } else {
                this.barTime.style.removeProperty('right')
                this.barTime.style['left'] = '0'
            }
            if (!this.player.__util.isMobile) this.barTime.style.removeProperty('display')
            this.barTime.innerText = this.player.__util.secondToTime(percentage * this.player.video.duration)
        }
        this.bar.addEventListener(this.player.__util.event.move, barHover)
        this.bar.addEventListener('mouseleave', () => this.barTime.style['display'] = 'none')
        const barClick = e => {
            let s = (e.clientX || e.changedTouches[0].clientX) - this.player.__util.getBoundingClientRectViewLeft(this.bar)
            let percentage = s < 0 ? 0 : s / this.bar.clientWidth
            percentage = Math.max(percentage, 0)
            percentage = Math.min(percentage, 1)
            this.player.seek(percentage * this.player.video.duration)
        }
        this.bar.addEventListener(this.player.__util.event.click, barClick)

        this.playButton.addEventListener(this.player.__util.event.click, () => {
            if (this.player.video.paused) this.player.play()
            else this.player.pause()
        })

        this.pipButton?.addEventListener(this.player.__util.event.click, () => {
            this.player.video['requestPictureInPicture']()
            this.player.__event.trigger('pip')
        })

        this.fullWebButton?.addEventListener(this.player.__util.event.click, () => {
            let f = this.player.container.classList.contains(('z-player-fulled'))
            if (f) {
                this.player.container.classList.remove('z-player-fulled')
            } else {
                if (document.fullscreenElement || document['mozFullScreenElement'] ||
                    document['webkitFullscreenElement'] || document['msFullscreenElement']) {
                    if (document['cancelFullScreen']) document['cancelFullScreen']()
                    else if (document['mozCancelFullScreen']) document['mozCancelFullScreen']()
                    else if (document['webkitCancelFullScreen']) document['webkitCancelFullScreen']()
                    else if (document['webkitCancelFullscreen']) document['webkitCancelFullscreen']()
                    else if (document['msCancelFullScreen']) document['msCancelFullScreen']()
                    else if (document['msExitFullscreen']) document['msExitFullscreen']()
                }
                this.player.container.classList.add('z-player-fulled')
            }
            this.player.__event.trigger('resize')
        })

        this.fullButton?.addEventListener(this.player.__util.event.click, () => {
            let f = document.fullscreenElement || document['mozFullScreenElement'] ||
                document['webkitFullscreenElement'] || document['msFullscreenElement']
            if (f) {
                if (document['cancelFullScreen']) document['cancelFullScreen']()
                else if (document['mozCancelFullScreen']) document['mozCancelFullScreen']()
                else if (document['webkitCancelFullScreen']) document['webkitCancelFullScreen']()
                else if (document['webkitCancelFullscreen']) document['webkitCancelFullscreen']()
                else if (document['msCancelFullScreen']) document['msCancelFullScreen']()
                else if (document['msExitFullscreen']) document['msExitFullscreen']()
            } else {
                if (this.player.container.classList.contains(('z-player-fulled'))) {
                    this.player.container.classList.remove('z-player-fulled')
                }
                if (this.player.container.requestFullscreen) this.player.container.requestFullscreen()
                else if (this.player.container['mozRequestFullScreen']) this.player.container['mozRequestFullScreen']()
                else if (this.player.container['webkitRequestFullscreen']) this.player.container['webkitRequestFullscreen']()
                else if (this.player.video['webkitEnterFullscreen']) this.player.video['webkitEnterFullscreen']()
                else if (this.player.video['webkitEnterFullScreen']) this.player.video['webkitEnterFullScreen']()
                else if (this.player.container['msRequestFullscreen']) this.player.container['msRequestFullscreen']()
            }
            this.player.__event.trigger('resize')
        })

        if (!this.player.__util.isMobile) {
            this.volumeButton.addEventListener(this.player.__util.event.enter, () => {
                this.rateWrap.style['display'] = 'none'
                this.volumeWrap.style.removeProperty('display')
                this.timer.pause(this.timer.setTimeout(() => this.volumeWrap.style['display'] = 'none', 500, 'volume_enter'))
            })
            this.volumeButton.addEventListener(this.player.__util.event.leave, () => this.timer.play('volume_enter'))
            this.volumeButton.addEventListener(this.player.__util.event.click, () => {
                if (this.player.video.volume > 0) {
                    this.player.volume(0)
                } else {
                    let volume = this.volume || this.player.property.volume
                    if (volume === 0) volume = .5
                    this.player.volume(volume)
                }
            })
            Controller.prototype.__volumeChange = e => {
                if (this.player.__util.getElementViewTop(this.volumeBar) <= 0) return
                let s = (e.clientY || e.changedTouches[0].clientY) - this.player.__util.getElementViewTop(this.volumeBar)
                let percentage = (this.volumeBar.clientHeight - s) / this.volumeBar.clientHeight
                this.player.volume(percentage)
            }
            Controller.prototype.__volumeRemove = () => {
                document.removeEventListener(this.player.__util.event.up, this.__volumeRemove)
                document.removeEventListener(this.player.__util.event.move, this.__volumeChange)
            }
            this.volumeWrap.addEventListener(this.player.__util.event.enter, () => this.timer.pause('volume_enter'))
            this.volumeWrap.addEventListener(this.player.__util.event.leave, () => this.timer.play('volume_enter'))
            this.volumeBar.addEventListener(this.player.__util.event.up, this.__volumeChange)
            this.volumeBar.addEventListener(this.player.__util.event.down, () => {
                document.addEventListener(this.player.__util.event.up, this.__volumeRemove)
                document.addEventListener(this.player.__util.event.move, this.__volumeChange)
            })
        }

        const showRateWrap = () => {
            if (this.volumeWrap) this.volumeWrap.style['display'] = 'none'
            this.rateWrap.style.removeProperty('display')
            for (let i = 0; i < this.rateItems.length; i++) {
                this.rateItems[i].classList.remove('z-player_controller-rate-checked')
            }
            let i = -1
            if (this.player.video.playbackRate === 2) i = 0
            else if (this.player.video.playbackRate === 1.5) i = 1
            else if (this.player.video.playbackRate === 1) i = 2
            else if (this.player.video.playbackRate === .75) i = 3
            else if (this.player.video.playbackRate === .5) i = 4
            if (i >= 0) this.rateItems[i].classList.add('z-player_controller-rate-checked')
            this.timer.setTimeout(() => this.rateWrap.style['display'] = 'none', this.player.__util.isMobile ? 1000 : 500, 'rate_enter')
            if (!this.player.__util.isMobile) this.timer.pause('rate_enter')
        }
        this.settingButton.addEventListener(this.player.__util.event[this.player.__util.isMobile ? 'click' : 'enter'], showRateWrap)
        this.settingButton.addEventListener(this.player.__util.event.leave, () => this.timer.play('rate_enter'))
        if (!this.player.__util.isMobile) {
            this.rateWrap.addEventListener(this.player.__util.event.enter, () => this.timer.pause('rate_enter'))
            this.rateWrap.addEventListener(this.player.__util.event.leave, () => this.timer.play('rate_enter'))
        }
        for (let i = 0; i < this.rateItems.length; i++) {
            this.rateItems[i].addEventListener(this.player.__util.event.click, () => {
                this.player.video.playbackRate = this.rateItems[i].innerText * 1
                for (let i = 0; i < this.rateItems.length; i++) {
                    this.rateItems[i].classList.remove('z-player_controller-rate-checked')
                }
                this.rateItems[i].classList.add('z-player_controller-rate-checked')
            })
        }
    }
}

export default player => new Controller(player)
